/**
 * @p.md
 * 
 * WasmRemoting 模块，提供 TypeScript 和 Go Actor 之间的远程通信功能
 */

import { PID } from '../actor/pid';
import { RootContext, RootContexts } from '../actor/rootContext';
import { WasmBridge, WasmBridgeFactory } from './wasmBridge';
import { ActorSystem } from '../actor/actorSystem';

/**
 * 消息头
 */
export interface MessageHeader {
  key: string;
  value: string;
}

/**
 * 远程通信消息封装
 */
export interface RemoteMessage {
  target: string;  // 目标 PID 的序列化形式
  sender?: string; // 发送者 PID 的序列化形式
  messageType: string; // 消息类型
  messageData: any; // 消息内容
  headers?: Map<string, string>; // 消息头
}

/**
 * WASM 远程通信服务
 */
export class WasmRemotingService {
  private bridge: WasmBridge;
  private rootContext: RootContext;
  private messageHandlers: Map<string, (message: any, sender?: PID) => void> = new Map();
  private pidCache: Map<string, PID> = new Map();
  private initialized: boolean = false;

  /**
   * 构造函数
   * @param bridge WASM 桥接器
   * @param rootContext 根上下文
   */
  constructor(bridge?: WasmBridge, rootContext?: RootContext) {
    this.bridge = bridge || WasmBridgeFactory.getInstance();
    this.rootContext = rootContext || RootContexts.create(new ActorSystem());
  }

  /**
   * 初始化远程通信服务
   */
  async initialize(): Promise<void> {
    if (this.initialized) {
      return;
    }

    // 确保 WASM 桥接初始化
    if (!this.bridge["initialized"]) {
      await this.bridge.initialize();
    }

    // 注册 TypeScript 端的消息处理函数
    this.bridge.registerTSFunction('OnRemoteMessage', this.handleRemoteMessage.bind(this));

    this.initialized = true;
    console.log('WASM 远程通信服务初始化成功');
  }

  /**
   * 发送消息到 Go Actor
   * @param target 目标 PID
   * @param message 消息内容
   * @param sender 发送者 PID
   * @param headers 消息头
   */
  async sendMessage(target: PID, message: any, sender?: PID, headers?: MessageHeader[]): Promise<void> {
    if (!this.initialized) {
      throw new Error('WASM 远程通信服务尚未初始化');
    }

    // 检查目标 PID 是否是远程 PID
    if (!this.isRemotePID(target)) {
      throw new Error('目标 PID 不是远程 PID');
    }

    // 准备消息
    const remoteMessage: RemoteMessage = {
      target: this.serializePID(target),
      messageType: message.constructor.name,
      messageData: message,
    };

    // 添加发送者（如果有）
    if (sender) {
      remoteMessage.sender = this.serializePID(sender);
    }

    // 添加消息头（如果有）
    if (headers && headers.length > 0) {
      remoteMessage.headers = new Map();
      for (const header of headers) {
        remoteMessage.headers.set(header.key, header.value);
      }
    }

    // 通过 WASM 桥接发送消息
    await this.bridge.invokeGoFunction('SendRemoteMessage', JSON.stringify(remoteMessage));
  }

  /**
   * 注册消息处理器
   * @param messageType 消息类型名称
   * @param handler 处理器函数
   */
  registerMessageHandler(messageType: string, handler: (message: any, sender?: PID) => void): void {
    this.messageHandlers.set(messageType, handler);
  }

  /**
   * 注销消息处理器
   * @param messageType 消息类型名称
   */
  unregisterMessageHandler(messageType: string): void {
    this.messageHandlers.delete(messageType);
  }

  /**
   * 处理来自 Go 的远程消息
   * @param messageJson 序列化的消息
   * @returns 处理结果
   */
  private handleRemoteMessage(messageJson: string): boolean {
    try {
      const remoteMessage = JSON.parse(messageJson) as RemoteMessage;
      
      // 解析目标 PID
      const targetPID = this.deserializePID(remoteMessage.target);
      
      // 解析发送者 PID（如果有）
      let senderPID: PID | undefined;
      if (remoteMessage.sender) {
        senderPID = this.deserializePID(remoteMessage.sender);
      }
      
      // 处理消息
      const handler = this.messageHandlers.get(remoteMessage.messageType);
      if (handler) {
        handler(remoteMessage.messageData, senderPID);
      } else {
        // 如果没有特定的处理器，则默认发送给目标 Actor
        this.rootContext.send(targetPID, remoteMessage.messageData);
      }
      
      return true;
    } catch (error) {
      console.error('处理远程消息失败:', error);
      return false;
    }
  }

  /**
   * 序列化 PID
   * @param pid PID 实例
   * @returns 序列化的 PID 字符串
   */
  private serializePID(pid: PID): string {
    return `${pid.address}/${pid.id}`;
  }

  /**
   * 反序列化 PID
   * @param serialized 序列化的 PID 字符串
   * @returns PID 实例
   */
  private deserializePID(serialized: string): PID {
    // 从缓存中获取 PID
    if (this.pidCache.has(serialized)) {
      return this.pidCache.get(serialized)!;
    }

    // 解析 PID 字符串
    const [address, id] = serialized.split('/');
    if (!address || !id) {
      throw new Error(`无效的 PID 字符串: ${serialized}`);
    }

    // 创建新的 PID
    const pid = new PID(address, id);
    
    // 缓存 PID
    this.pidCache.set(serialized, pid);
    
    return pid;
  }

  /**
   * 检查 PID 是否是远程 PID
   * @param pid 要检查的 PID
   * @returns 是否是远程 PID
   */
  private isRemotePID(pid: PID): boolean {
    // 检查 address 是否包含 WASM 或远程主机标识
    return pid.address.includes('wasm:') || pid.address.includes('remote:');
  }
}

/**
 * 创建远程 PID
 * @param id Actor ID
 * @returns 远程 PID
 */
export function createRemotePID(id: string): PID {
  return new PID('wasm:remote', id);
}

/**
 * WASM 远程通信服务工厂
 */
export class WasmRemotingFactory {
  private static instance: WasmRemotingService;

  /**
   * 获取 WASM 远程通信服务实例
   * @param bridge 可选的 WASM 桥接器实例
   * @param rootContext 可选的根上下文
   * @returns WASM 远程通信服务实例
   */
  static getInstance(bridge?: WasmBridge, rootContext?: RootContext): WasmRemotingService {
    if (!WasmRemotingFactory.instance) {
      WasmRemotingFactory.instance = new WasmRemotingService(bridge, rootContext);
    }
    return WasmRemotingFactory.instance;
  }
} 